Overview
Fetches real-time lists of stocks that have hit upper or lower circuit breakers (price freeze limits) using the Dhan ScanX Analytics API. Implements 3-tier fallback to Dhan’s Next.js API and web scraping.
Source: fetch_circuit_stocks.py
Phase: Phase 2 (Enrichment)
Output: upper_circuit_stocks.json, lower_circuit_stocks.json
API Endpoint
POST https://ow-scanx-analytics.dhan.co/customscan/fetchdt
Request Payload
Maximum number of results to return
List of fields to include in response
Example Request (Upper Circuit)
{
"data": {
"sort": "Mcap",
"sorder": "desc",
"count": 500,
"fields": ["Sym", "DispSym", "Ltp", "PPerchange", "Mcap", "Volume", "High5yr", "Low1Yr", "High1Yr", "Pe", "Pb", "DivYeild"],
"params": [
{"field": "LiveData.UpperCircuitBreak", "op": "", "val": "1"},
{"field": "OgInst", "op": "", "val": "ES"},
{"field": "Seg", "op": "", "val": "E"}
],
"pgno": 1
}
}
Example Request (Lower Circuit)
{
"data": {
"sort": "Mcap",
"sorder": "desc",
"count": 500,
"fields": ["Sym", "DispSym", "Ltp", "PPerchange", "Mcap", "Volume", "High5yr", "Low1Yr", "High1Yr", "Pe", "Pb", "DivYeild"],
"params": [
{"field": "LiveData.LowerCircuitBreak", "op": "", "val": "1"},
{"field": "OgInst", "op": "", "val": "ES"},
{"field": "Seg", "op": "", "val": "E"}
],
"pgno": 1
}
}
Configuration
scans_config = {
"upper_circuit_stocks.json": {
"val": "1",
"field": "LiveData.UpperCircuitBreak",
"web_key": "stocks/market/shares-with-upper-circuit",
"web_url": "https://dhan.co/stocks/market/shares-with-upper-circuit/"
},
"lower_circuit_stocks.json": {
"val": "1",
"field": "LiveData.LowerCircuitBreak",
"web_key": "stocks/market/lower-circuit-stocks",
"web_url": "https://dhan.co/stocks/market/lower-circuit-stocks/"
}
}
Function Signatures
get_build_id()
def get_build_id():
"""
Dynamically fetch the Next.js buildId from Dhan website.
Returns:
str: Build ID string, or None if extraction fails
"""
fetch_circuit_stocks()
def fetch_circuit_stocks():
"""
Main function that fetches both upper and lower circuit stocks using 3-tier fallback.
Writes upper_circuit_stocks.json and lower_circuit_stocks.json to current directory.
"""
Output Structure
Dividend yield percentage
Example Output
[
{
"Symbol": "TATASTEEL",
"Name": "Tata Steel Limited",
"LTP": 145.50,
"ChangePercent": 19.95,
"MarketCap": 178456.32,
"Volume": 85234567,
"High5Yr": 165.00,
"High1Yr": 155.00,
"Low1Yr": 95.00,
"PE": 12.5,
"PB": 1.8,
"DivYield": 2.5
}
]
Data Sources
The script implements a 3-tier fallback strategy:
Primary: ScanX Analytics API
Direct POST request to customscan/fetchdt endpoint (see payload above).
Secondary: Dhan Next.js JSON API
GET https://dhan.co/_next/data/{buildId}/{web_key}.json
Extracts stock list from nested pageProps structure.
Tertiary: Web Scraping
Fallback scraping from web URLs, extracting __NEXT_DATA__ script block.
Dependencies
requests — HTTP client
json — JSON parsing
re — Regex for buildId extraction
BeautifulSoup — HTML parsing for fallback scraping
Error Handling
- 3-tier fallback ensures high reliability
- 10-second timeout for all HTTP requests
- Graceful degradation through each fallback layer
- Prints detailed progress messages for debugging
if success:
print(f" Successfully found {len(cleaned_list)} stocks via ScanX API.")
else:
print(f" Critical failure: Could not fetch {filename}.")
Field Mapping
API response fields are mapped to consistent output format:
cleaned_list.append({
"Symbol": item.get('Sym'),
"Name": item.get('DispSym'),
"LTP": item.get('Ltp'),
"ChangePercent": item.get('PPerchange'),
"MarketCap": item.get('Mcap'),
"Volume": item.get('Volume'),
"High5Yr": item.get('High5yr'),
"High1Yr": item.get('High1Yr'),
"Low1Yr": item.get('Low1Yr'),
"PE": item.get('Pe'),
"PB": item.get('Pb'),
"DivYield": item.get('DivYeild')
})
Usage Example
python3 fetch_circuit_stocks.py
Expected Output:
Processing upper_circuit_stocks.json...
Primary Fetch: ScanX Analytics API...
Successfully found 23 stocks via ScanX API.
Processing lower_circuit_stocks.json...
Primary Fetch: ScanX Analytics API...
Successfully found 15 stocks via ScanX API.
Integration
This script is part of Phase 2 (Enrichment) in the EDL Pipeline. The output files are consumed by:
bulk_market_analyzer.py — Used for market sentiment analysis
- Analytics dashboards for intraday monitoring
Run via master pipeline:
python3 run_full_pipeline.py